package com.jmex.physics.impl.bullet;

import java.util.ArrayList;
import java.util.List;

import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Spatial;
import com.jmex.physics.StaticPhysicsNode;
import com.jmex.physics.impl.bullet.geometry.BulletGeometry;
import com.jmex.physics.material.Material;

public class BulletStaticPhysicsNode extends StaticPhysicsNode {

	private BulletPhysicsSpace space;
	
	private BulletRigidBody body;
	
	private Vector3f centerOfMass = new Vector3f();
	private Vector3f tempPos = new Vector3f();
	private Vector3f tempScale = new Vector3f();
	
    private Vector3f lastTranslation = new Vector3f();
    private Quaternion lastRotation = new Quaternion();

    private List<BulletGeometry> collisionShapes = new ArrayList<BulletGeometry>();
    private boolean dirty;
 
    public BulletStaticPhysicsNode( BulletPhysicsSpace space ) {
        this.space = space;
    }

	@Override
	public BulletPhysicsSpace getSpace() {
		return space;
	}

    public boolean isTouched()
    {
    	if(body==null)
    		return false;
    	return !(getWorldTranslation().equals(lastTranslation) &&
    			getWorldRotation().equals(lastRotation));
    }

    void sync()
    {
    	lastTranslation.set(getWorldTranslation());
    	lastRotation.set(getWorldRotation());
    }

	private void computeMass() {
        float mass = 0f;
        float tempMass;
        centerOfMass=new Vector3f();
        Material mat;
        for ( BulletGeometry geom : collisionShapes ) {
            getWorldScale().mult( geom.getLocalScale(), tempScale );
            tempPos.set(geom.getLocalTranslation().divide( tempScale ));
        	mat = geom.getMaterial();
        	if(mat==null) mat=getMaterial();
            tempMass = geom.getVolume() * mat.getDensity();
            mass += tempMass;
            if(mass>0)
            	centerOfMass.interpolate(tempPos, tempMass/mass);
        }
        if(mass==0)
        	mass=1f;
        dirty = true;
	}

    @Override
    public int attachChild( Spatial child ) {
        int index = super.attachChild( child );
        if ( child instanceof BulletGeometry ) {
            dirty = true;
            collisionShapes.add( (BulletGeometry) child );
        }
        return index;
    }

    @Override
    public int detachChild( Spatial child ) {
        int index = super.detachChild( child );
        if ( child instanceof BulletGeometry ) {
            dirty = true;
            collisionShapes.remove( child );
        }
        return index;
    }

    Vector3f getCenterOfMass(Vector3f store) {
		if(store==null)
			store = new Vector3f();
		store.set(centerOfMass);
		return store;
	}

	void setCenterOfMass(Vector3f centerOfMass) {
		this.centerOfMass = centerOfMass;
	}

    public void rebuildRigidBody() {

        updateWorldVectors();

        computeMass(); //Nonsensical, I know, but necessary to get the right coords into Bullet
        
        if(body==null)
        	body = new BulletRigidBody(this,collisionShapes);
        else
        	body.setCollisionShapes(collisionShapes);
        
        body.updateRigidBody();
        
        dirty=false;
        sync();
        for(BulletGeometry geom : collisionShapes)
        	geom.setDirty(false);
    }

    public boolean isDirty() {
        if ( dirty ) {
            return true;
        }
        for ( BulletGeometry geom : this.collisionShapes ) {
            if ( geom.isDirty() ) {
                return true;
            }
        }
        return false;
    }

	BulletRigidBody getBody() {
		return body;
	}

}
